from contextlib import closing
import json
from typing import Any
import requests
import telnetlib

from utils.file_util import FileUtil


class RequestUtil:
    chrome_headers = {
        "Accept": "application/json, text/plain, */*",
        "Accept-Encoding": "gzip, deflate",
        "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
        "Connection": "keep-alive",
        "Content-Length": "0",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
        "Content-Type": "application/json;charset=UTF-8",
    }

    def __init__(self, root_url: str, proxy: dict | None = None, debug: bool = False):
        self.root_url = root_url
        self.headers = RequestUtil.chrome_headers
        self.proxies = proxy
        self.cookies = {}
        self.timeout = 30
        self.debug = debug

    def init_headers(self, host: str, origin: str, referer: str):
        self.headers["Host"] = host
        self.headers["Origin"] = origin
        self.headers["Referer"] = referer

    def request(
        self, method: str, path: str, params: dict = None, body: Any = None
    ) -> requests.Response:
        if self.debug:
            print(f"{method}:params: {params}")

        data = None
        if body != None:
            data = json.dumps(body)
            if self.debug:
                print(f"put:data: {data}")

        return requests.request(
            url=self.get_url(path),
            method=method,
            params=params,
            data=data,
            headers=self.headers,
            cookies=self.cookies,
            proxies=self.proxies,
            timeout=self.timeout,
        )

    def get(self, path: str, params: dict = None) -> requests.Response:
        return self.request("GET", path, params=params)

    def put(self, path: str, params: dict = None, body: Any = None):
        return self.request("PUT", path, params=params, body=body)

    def post(self, path: str, params: dict = None, body: Any = None):
        return self.request("POST", path, params=params, body=body)

    def delete(self, path: str, params: dict = None, body: Any = None):
        return self.request("DELETE", path, params=params, body=body)

    def download_image(self, path: str, file: str):
        with closing(requests.get(url=self.get_url(path), stream=True)) as response:
            if response.status_code != 200:
                raise Exception(f"'{path}' is not found")
            FileUtil.make_parent(file)
            with open(file, "wb") as file:
                for data in response.iter_content(1024):
                    file.write(data)

    def get_url(self, path: str) -> str:
        url = f"{self.root_url}{path}"
        if self.debug:
            print(f"url: {url}", flush=True)
        return url
